#include "send_image.h"
#include "config.h"
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
char txxxx_dat[40960] = {0};
/* 发送视频数据到服务器 */
void *send_video_to_server(void *arg)
{
    int                ret, recv_len, set_udp_size;
    unsigned int       video_data_len;    /* 头部信息解析出来的图像数据大小 */
    unsigned int       want_len;          /* 想要接收的长度 */
    int                mjpeg_sockfd;
    struct sockaddr_in mjpeg_addr;
    int                server_sockfd;
    int                server_udp_port = *(int *)arg;
    struct sockaddr_in server_addr;
    char               *buf, *pbegin, *pend, *pic_data, tbuf[10];
    int                offset;

    /* ====== 01.创建 TCP 连接 (用于从 mjpeg-streamer 获取视频) ====== */

    /* 流式套接字 */
    mjpeg_sockfd = socket(AF_INET, SOCK_STREAM, 0);

    /* 判断文件描述符是否创建成功 */
    if (mjpeg_sockfd == -1)
    {
        perror("tcp_sockfd create failed");
        exit(1);
    }

    /* 向 mjpeg-streamer服务器 发起 TCP 连接 */
    memset(&mjpeg_addr, 0, sizeof(mjpeg_addr));
    mjpeg_addr.sin_family = AF_INET;
    mjpeg_addr.sin_port = htons(MJPEG_PORT);
    mjpeg_addr.sin_addr.s_addr = inet_addr(MJPEG_ADDR);

    ret = connect(mjpeg_sockfd, (const struct sockaddr *)&mjpeg_addr, sizeof(mjpeg_addr));

    /* 判断套接字是否连接成功 */
    if (ret == -1)
    {
        perror("tcp_sockfd connect to mjpeg server failed");
        exit(1);
    }

    /* 打印调试 */
    printf("connect to mjpeg server succeed\n");

    /* ====== 02.创建 UDP 套接字 (用于向 服务器 发送视频) ====== */

    /* 数据报套接字 */
    server_sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    /* 判断文件描述符是否创建成功 */
    if (server_sockfd == -1)
    {
        perror("server udp_sockfd create failed");
        exit(1);
    }

    /* 设置UDP 发送 缓冲区 */
    set_udp_size = PIC_MAX_SIZE;

    if (setsockopt(server_sockfd, SOL_SOCKET, SO_SNDBUF, &set_udp_size, sizeof(set_udp_size)) != 0)
    {
        perror("server udp_sockfd set size failed");
        exit(1);
    }

    /* 设置udp服务器的地址信息 */
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(server_udp_port);     /* udp_port 来自 ali server 返回 */
    server_addr.sin_addr.s_addr = inet_addr(ALI_PNET_ADDR);

    /* ====== 03.让 mjpeg-streamer 准备发送图像数据 */

    /*
     * mjpeg-streamer 服务器动作:
     * 1.接收命令 (GET /?action=stream)
     * 2.验证退出循环 (2字节)
     * 3.返回头部信息
     */

    /* 申请内存空间用于存储一帧图像数据 */
    buf = (char *) malloc(PIC_MAX_SIZE);

    /* 判断内存空间是否分配成功 */
    if (buf == NULL)
    {
        perror("malloc memory for recv pic failed");
        exit(1);
    }

    pic_data = (char *) malloc(PIC_MAX_SIZE);

    /* 判断内存空间是否分配成功 */
    if (pic_data == NULL)
    {
        perror("malloc memory for save pic failed");
        exit(1);
    }

    /* 发送请求图像的命令 */
    memset(buf, 0, PIC_MAX_SIZE);
    strcpy(buf, "GET /?action=stream\n");
    ret = send(mjpeg_sockfd, buf, strlen(buf), 0);

    /* 判断发送数据是否成功 */
    if (ret == -1)
    {
        perror("send request order to mjpeg server failed");
        exit(1);
    }

    /* 发送验证命令 (小于2个字节) */
    memset(buf, 0, PIC_MAX_SIZE);
    strcpy(buf, "q\n");
    ret = send(mjpeg_sockfd, buf, 2, 0);

    /* 判断发送数据是否成功 */
    if (ret == -1)
    {
        perror("send verify order to mjpeg server failed");
        exit(1);
    }

    /* 接收头部信息 */
    memset(buf, 0, PIC_MAX_SIZE);
    ret = recv(mjpeg_sockfd, buf, PIC_MAX_SIZE, 0);

    /* 判断接收数据是否成功 */
    if (ret == -1)
    {
        perror("recv head info from mjpeg server failed");
    }

    while(1)
    {
        /* ====== 04.从 mjpeg-streamer 服务器 读取 视频数据 ====== */

        /*
         * mjpeg-streamer 服务器动作:
         * 4.while(1)
         *   {
         *       发送一帧头部信息 (PIC_FRAME_HEAD_SIZE Byte)
         *       发送一帧图像数据
         *       发送一帧尾部信息 (PIC_FRAME_TAIL_SIZE Byte)
         *   }
         */

        /* 接收一帧头部信息 */
        memset(buf, 0, PIC_MAX_SIZE);
        ret = recv(mjpeg_sockfd, buf, PIC_FRAME_HEAD_SIZE, 0);

        /* 判断接收数据是否成功 */
        if (ret == -1)
        {
            perror("recv header info from mjpeg server failed");
        }

        /* 解析出图像大小 (数据内容: Content-Length: %d\r\nX-Timestamp)*/
        pbegin = strstr(buf, "Content-Length");       /* 找到子串 "Content-Length: " */

        if (pbegin != NULL)
        {
            pend = strstr(pbegin, "X-Timestamp");       /* 找到子串 "X-Timestamp" */

            if (pend != NULL)
            {
                /* 拷贝size字段 */
                memset(tbuf, 0, sizeof(tbuf));
                memcpy(tbuf, pbegin + strlen("Content-Length: "), 
                       (int) ((pend - 2) - (pbegin + strlen("Content-Length: "))));

                /* char 转换为 int 得到该帧图片长度 */
                video_data_len = atoi(tbuf);
            }
        }
        else
        {
            continue;   /* 重新接收头部信息 */
        }

        /* 循环接收一帧图像数据 (指定大小) */
        memset(buf, 0, PIC_MAX_SIZE);
        memset(pic_data, 0, PIC_MAX_SIZE);
        want_len = video_data_len;  /* 记录想要接收数据的大小 */
        offset = 0;                 /* offset 清0 */

        while(1)
        {
            /* 接收想要的长度 */
            recv_len = recv(mjpeg_sockfd, buf, want_len, 0);

            /* 判断接收数据是否成功 */
            if (recv_len == -1)
            {
                perror("recv video data from mjpeg server failed");
                exit(1);  /* mjpeg server 故障，直接退出 */
            }

            /* 判断是否接收完毕 */
            if (recv_len == want_len)
            {
                memcpy((pic_data + offset), buf, recv_len);
                break;  /* 接收一帧图像完毕，退出循环 */
            }
            else
            {
                memcpy((pic_data + offset), buf, recv_len);
                want_len -= recv_len;     /* 计算剩余字节数 */
                offset += recv_len;       /* 计算偏移值 */
            }
        }

        /* 向 阿里云服务器发送 视频数据 video_data_len */
        ret = sendto(server_sockfd, pic_data, video_data_len, 0, 
                     (const struct sockaddr *) &server_addr, sizeof(server_addr));

        /* 判断发送数据是否成功 */
        if (ret == -1)
        {
            perror("send video data to ali server failed");
        }
	else
	{
		printf("send video data to ali server, size is %d\n", video_data_len);
	}

        /* 接收一帧尾部信息 */
        memset(buf, 0, PIC_MAX_SIZE);
        ret = recv(mjpeg_sockfd, buf, PIC_FRAME_TAIL_SIZE, 0);

        /* 判断接收数据是否成功 */
        if (ret == -1)
        {
            perror("recv tail data from mjpeg server failed");
        }
    }
}
